/*************************************************
  * 描述：
  *
  * File：logger_p.h
  * Author：chenyujin@mozihealthcare.cn
  * Date：2025/9/2
  * Update：
  * ************************************************/
#ifndef COREXI_COMMON_PC_LOGGER_P_H
#define COREXI_COMMON_PC_LOGGER_P_H
#include "yamltool/yamltool_p.h"
#include <common/logger/logger.h>
#include <memory>
#include <mutex>
#include <spdlog/spdlog.h>

class LogPrivate
{
public:
	/**
     * 删除拷贝构造，确保单例
     */
	LogPrivate(const LogPrivate&) = delete;

	/**
	 * 删除移动构造，确保单例
	 */
	LogPrivate(const LogPrivate&&) = delete;

	/**
     * 删除赋值符号重载，确保单例
     * @return
     */
	LogPrivate& operator=(const LogPrivate&) = delete;
	LogPrivate& operator=(const LogPrivate&&) = delete;


	/**
	 * 手动修改读取配置文件的路径
	 * 若不调用此方法修改，默认读取位置为可执行程序所在路径下
	 * @param configFilePath 配置文件路径
	 */
	static void setConfigPath(const std::string& configFilePath);

	/**
     * 输出带行号的trace级别日志文本，严重级别0
     * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
     * @param fileName 日志输出位置文件名，应传入宏__FILE__
     * @param fileLine 日志输出位置行号，应传入宏__LINE__
     * @param function 日志输出所在函数，应传入宏__FUNCTION__
     * @param msgList 日志文本信息列表
     */
	static void trace(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);

	/**
     * 输出带行号的debug级别日志文本，严重级别1
     * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
     * @param fileName 日志输出位置文件名，应传入宏__FILE__
     * @param fileLine 日志输出位置行号，应传入宏__LINE__
     * @param function 日志输出所在函数，应传入宏__FUNCTION__
     * @param msgList 日志文本信息列表
     */
	static void debug(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);

	/**
     * 输出带行号的info级别日志文本，严重级别2
     * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
     * @param fileName 日志输出位置文件名，应传入宏__FILE__
     * @param fileLine 日志输出位置行号，应传入宏__LINE__
     * @param function 日志输出所在函数，应传入宏__FUNCTION__
     * @param msgList 日志文本信息列表
     */
	static void info(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);


	/**
     * 输出带行号的warn级别日志文本，严重级别3
     * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
     * @param fileName 日志输出位置文件名，应传入宏__FILE__
     * @param fileLine 日志输出位置行号，应传入宏__LINE__
     * @param function 日志输出所在函数，应传入宏__FUNCTION__
     * @param msgList 日志文本信息列表
     */
	static void warn(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);


	/**
     * 输出带行号的error级别日志文本，严重级别4
     * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
     * @param fileName 日志输出位置文件名，应传入宏__FILE__
     * @param fileLine 日志输出位置行号，应传入宏__LINE__
     * @param function 日志输出所在函数，应传入宏__FUNCTION__
     * @param msgList 日志文本信息列表
     */
	static void error(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);


	/**
	 * 输出带行号的critical级别日志文本，严重级别5
	 * fileName,fileLine,funtion参数可使用宏定义GET_LINE取代
	 * @param fileName 日志输出位置文件名，应传入宏__FILE__
	 * @param fileLine 日志输出位置行号，应传入宏__LINE__
	 * @param function 日志输出所在函数，应传入宏__FUNCTION__
	 * @param msgList 日志文本信息列表
	 */
	static void critical(const char* fileName, int fileLine, const char* function, const std::initializer_list<std::any>& msgList);

	/**
     * 创建一个输出到流的日志输出器，并添加到日志对象中
     * 值得注意的是，这种方式不支持输出线程号
     * @param stream 要输出到的流对象
     * @param flush 是否立即刷新流缓冲区
     * @param level 日志级别
     */
	static void setStreamOutPut(std::ostringstream& stream, bool flush = false, LogLevel level = LogLevel::Trace);


	/**
	 * 设置日志回调函数，每当日志输出时，调用回调函数
	 * @param logCallBack 日志回调函数
	 * @param level 日志级别
	 */
	static void setCallBackSink(const std::function<void(const LogMsg& logMsg)>& logCallBack, LogLevel level = LogLevel::Trace);

private:
	/**
     * 构造
     */
	LogPrivate();

	/**
     * 析构，默认
     */
	~LogPrivate() = default;

	/**
     * 进行初始化
     * @return
     */
	static LogPrivate* getInstance();

	/**
     * 获取内部日志对象spdlog指针
     * @return
     */
	std::shared_ptr<spdlog::logger> getLogger();

	/**
     * 子程序，用来读取ini配置文件内容
     */
	void loadConfigFile(const std::string& configFilePath);

	/**
     * 子程序，一套默认配置，当配置文件读取失败时调用
     */
	void defaultConfig(const std::string& configFilePath);

	void deleteOldConfig(const std::string& configFilePath);

	/**
     * 子程序，用于检测ini中属性对应值是否为空，为空则打印错误并返回默认属性值
     * @param itemValue 属性值
     * @param itemName 属性名
     * @param defaultValue 默认属性值
     * @return
     */
	std::string getItemValue(const std::string& itemValue, const std::string& itemName,
							 const std::string& defaultValue);

	/**
     * 子程序，用于检测sink输出路径是否存在，不存在则打印错误
     * @param sinkType
     * @param filePath
     */
	bool checkSinkFilePath(const std::string& sinkType, const std::string& filePath);

	/**
	 * 用于拼接字符串
	 * @param msgList
	 * @return
	 */
	static std::string linkString(const std::initializer_list<std::any>& msgList);

private:
	// 静态互斥锁，用于确保线程安全
	static std::mutex s_mutex;
	// 静态对象指针
	static LogPrivate* s_instance;
	// spdlog库logger类对象指针
	std::shared_ptr<spdlog::logger> m_logger;

	static std::string m_configFilePath;

	static bool m_traceShowLine;
	static bool m_debugShowLine;
	static bool m_infoShowLine;
	static bool m_warnShowLine;
	static bool m_errorShowLine;
	static bool m_criticalShowLine;
};

#endif//COREXI_COMMON_PC_LOGGER_P_H
